const axios = require('axios');
const dayjs = require('dayjs');
const logger = require('../config/logger');
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

class QPay {
  constructor() {
    this.baseUrl = 'https://merchant.qpay.mn/v2';
    this.username = process.env.QPAY_USERNAME;
    this.password = process.env.QPAY_PASSWORD;
    this.accessToken = null;
    this.ebarimtEnabled = process.env.QPAY_EBARIMT_ENABLED === 'true';
  }

  // 验证发票数据
  validateInvoiceData(invoiceData) {
    const requiredFields = [
      'invoice_code',
      'sender_invoice_no',
      'invoice_receiver_code',
      'invoice_description',
      'amount'
    ];

    const missingFields = requiredFields.filter(field => !invoiceData[field]);
    if (missingFields.length > 0) {
      throw new Error(`缺少必要字段: ${missingFields.join(', ')}`);
    }

    if (typeof invoiceData.amount !== 'number' || invoiceData.amount <= 0) {
      throw new Error('金额必须大于0');
    }

    if (invoiceData.callback_url && !this.isValidUrl(invoiceData.callback_url)) {
      throw new Error('回调URL格式无效');
    }

    return true;
  }

  // 验证支付检查参数
  validatePaymentCheckParams(objectType, objectId) {
    if (!objectType || !objectId) {
      throw new Error('object_type 和 object_id 是必需的');
    }

    if (!['INVOICE'].includes(objectType)) {
      throw new Error('无效的object_type');
    }

    return true;
  }

  // 验证支付列表参数
  validatePaymentListParams(objectType, objectId, startDate, endDate) {
    if (!objectType || !objectId) {
      throw new Error('object_type 和 object_id 是必需的');
    }

    if (!startDate || !endDate) {
      throw new Error('start_date 和 end_date 是必需的');
    }

    if (!dayjs(startDate).isValid() || !dayjs(endDate).isValid()) {
      throw new Error('日期格式无效');
    }

    if (dayjs(startDate).isAfter(dayjs(endDate))) {
      throw new Error('开始日期不能晚于结束日期');
    }

    return true;
  }

  // 验证电子收据参数
  validateEbarimtParams(paymentId, ebarimtReceiverType) {
    if (!paymentId) {
      throw new Error('payment_id 是必需的');
    }

    if (!['CITIZEN', 'BUSINESS'].includes(ebarimtReceiverType)) {
      throw new Error('无效的ebarimt_receiver_type');
    }

    return true;
  }

  // 验证URL格式
  isValidUrl(url) {
    try {
      new URL(url);
      return true;
    } catch {
      return false;
    }
  }

  // 从数据库获取访问令牌
  async getStoredToken() {
    try {
      const tokenRecord = await prisma.qpayToken.findFirst({
        orderBy: {
          createdAt: 'desc'
        }
      });

      if (tokenRecord && this.isTokenValid(tokenRecord.expiresAt)) {
        this.accessToken = tokenRecord.token;
        return this.accessToken;
      }
      return null;
    } catch (error) {
      logger.error('获取存储的QPay令牌失败:', error);
      return null;
    }
  }

  // 检查令牌是否有效
  isTokenValid(expiresAt) {
    if (!expiresAt) return false;
    // 提前5分钟过期，避免边界情况
    return dayjs(expiresAt).subtract(5, 'minute').isAfter(dayjs());
  }

  // 存储访问令牌到数据库
  async storeToken(token, expiresAt) {
    try {
      await prisma.qpayToken.create({
        data: {
          token,
          expiresAt,
          createdAt: new Date()
        }
      });
    } catch (error) {
      logger.error('存储QPay令牌失败:', error);
    }
  }

  // 获取访问令牌
  async getAccessToken() {
    try {
      // 首先尝试从数据库获取有效的令牌
      const storedToken = await this.getStoredToken();
      if (storedToken) {
        return storedToken;
      }

      // 如果没有有效的存储令牌，则请求新的令牌
      const response = await axios.post(`${this.baseUrl}/auth/token`, null, {
        auth: {
          username: this.username,
          password: this.password
        }
      });

      this.accessToken = response.data.access_token;
      
      // 计算令牌过期时间（通常为24小时）
      const expiresAt = dayjs().add(24, 'hour').toDate();
      
      // 存储新令牌
      await this.storeToken(this.accessToken, expiresAt);
      
      return this.accessToken;
    } catch (error) {
      logger.error('获取QPay访问令牌失败:', error);
      throw error;
    }
  }

  // 刷新访问令牌
  async refreshToken() {
    try {
      const response = await axios.post(`${this.baseUrl}/auth/refresh`, null, {
        headers: {
          Authorization: `Bearer ${this.accessToken}`
        }
      });

      this.accessToken = response.data.access_token;
      
      // 计算新的过期时间
      const expiresAt = dayjs().add(24, 'hour').toDate();
      
      // 存储新令牌
      await this.storeToken(this.accessToken, expiresAt);
      
      return this.accessToken;
    } catch (error) {
      logger.error('刷新QPay访问令牌失败:', error);
      throw error;
    }
  }

  // 确保token有效的中间件方法
  async ensureValidToken() {
    try {
      // 检查当前token是否有效
      if (!this.accessToken) {
        await this.getAccessToken();
        return;
      }

      // 尝试从数据库获取最新的token
      const storedToken = await this.getStoredToken();
      if (storedToken) {
        this.accessToken = storedToken;
        return;
      }

      // 如果数据库中没有有效token，尝试刷新当前token
      try {
        await this.refreshToken();
      } catch (refreshError) {
        // 如果刷新失败，获取新token
        await this.getAccessToken();
      }
    } catch (error) {
      logger.error('确保QPay令牌有效失败:', error);
      throw error;
    }
  }

  // 创建发票
  async createInvoice(invoiceData) {
    try {
      this.validateInvoiceData(invoiceData);
      await this.ensureValidToken();

      const response = await axios.post(`${this.baseUrl}/invoice`, invoiceData, {
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${this.accessToken}`
        }
      });
      return response.data;
    } catch (error) {
      logger.error('创建QPay发票失败:', error);
      throw error;
    }
  }

  // 取消发票
  async cancelInvoice(invoiceId) {
    try {
      await this.ensureValidToken();

      const response = await axios.delete(`${this.baseUrl}/invoice/${invoiceId}`, {
        headers: {
          Authorization: `Bearer ${this.accessToken}`
        }
      });
      return response.data;
    } catch (error) {
      logger.error('取消QPay发票失败:', error);
      throw error;
    }
  }

  // 获取支付信息
  async getPayment(paymentId) {
    try {
      await this.ensureValidToken();

      const response = await axios.get(`${this.baseUrl}/payment/${paymentId}`, {
        headers: {
          Authorization: `Bearer ${this.accessToken}`
        }
      });
      return response.data;
    } catch (error) {
      logger.error('获取QPay支付信息失败:', error);
      throw error;
    }
  }

  // 检查支付状态
  async checkPayment(objectType, objectId, pageNumber = 1, pageLimit = 100) {
    try {
      this.validatePaymentCheckParams(objectType, objectId);
      await this.ensureValidToken();

      const response = await axios.post(
        `${this.baseUrl}/payment/check`,
        {
          object_type: objectType,
          object_id: objectId,
          offset: {
            page_number: pageNumber,
            page_limit: pageLimit
          }
        },
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.accessToken}`
          }
        }
      );
      logger.info('QPay支付状态检查结果:', response.data);
      return response.data;
    } catch (error) {
      logger.error('检查QPay支付状态失败:', error);
      throw error;
    }
  }

  // 取消支付
  async cancelPayment(paymentId, callbackUrl, note) {
    try {
      await this.ensureValidToken();

      const response = await axios.delete(
        `${this.baseUrl}/payment/cancel/${paymentId}`,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.accessToken}`
          },
          data: {
            callback_url: callbackUrl,
            note: note
          }
        }
      );
      return response.data;
    } catch (error) {
      logger.error('取消QPay支付失败:', error);
      throw error;
    }
  }

  // 获取支付列表
  async getPaymentList(objectType, objectId, startDate, endDate, pageNumber = 1, pageLimit = 100) {
    try {
      this.validatePaymentListParams(objectType, objectId, startDate, endDate);
      await this.ensureValidToken();

      const response = await axios.post(
        `${this.baseUrl}/payment/list`,
        {
          object_type: objectType,
          object_id: objectId,
          start_date: startDate,
          end_date: endDate,
          offset: {
            page_number: pageNumber,
            page_limit: pageLimit
          }
        },
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.accessToken}`
          }
        }
      );
      return response.data;
    } catch (error) {
      logger.error('获取QPay支付列表失败:', error);
      throw error;
    }
  }

  // 创建电子收据
  async createEbarimt(paymentId, ebarimtReceiverType = 'CITIZEN') {
    try {
      // 如果电子收据功能未启用，直接返回null
      if (!this.ebarimtEnabled) {
        logger.info('电子收据功能未启用，跳过创建', { payment_id: paymentId });
        return null;
      }

      this.validateEbarimtParams(paymentId, ebarimtReceiverType);
      await this.ensureValidToken();

      const response = await axios.post(
        `${this.baseUrl}/ebarimt/create`,
        {
          payment_id: paymentId,
          ebarimt_receiver_type: ebarimtReceiverType
        },
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.accessToken}`
          }
        }
      );
      return response.data;
    } catch (error) {
      // 如果是EBARIMT_NOT_ENABLED错误，记录日志并返回null
      if (error.response?.data?.error === 'EBARIMT_NOT_ENABLED') {
        logger.info('商户未启用电子收据功能，跳过创建', { payment_id: paymentId });
        return null;
      }
      logger.error('创建QPay电子收据失败:', error);
      throw error;
    }
  }

  // 退款支付
  async refundPayment({ payment_id, amount, reason }) {
    try {
      if (!payment_id) {
        throw new Error('payment_id 是必需的');
      }

      await this.ensureValidToken();

      const response = await axios.delete(
        `${this.baseUrl}/payment/refund/${payment_id}`,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.accessToken}`
          },
          data: {
            amount: amount,
            reason: reason
          }
        }
      );

      logger.info('QPay退款成功:', { payment_id, response: response.data });
      return response.data;
    } catch (error) {
      logger.error('QPay退款失败:', error);
      throw error;
    }
  }
}

module.exports = new QPay();